package ch.ti.bfh.app.loodel.web.controller;

import ch.ti.bfh.app.loodel.service.timeslotschedule.MemberTimeSlotScheduleService;
import ch.ti.bfh.app.loodel.service.timeslotschedule.TimeSlotScheduleData;
import ch.ti.bfh.app.loodel.service.timeslotschedule.TimeSlotScheduleSearchCriteria;
import ch.ti.bfh.app.loodel.service.vote.LearningEventVoteData;
import ch.ti.bfh.app.loodel.web.model.LoodelScheduleEvent;
import ch.ti.bfh.app.loodel.web.model.MemberTimeSlotScheduleModel;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.primefaces.event.ScheduleEntrySelectEvent;
import org.primefaces.model.LazyScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.faces.context.FacesContext;
import javax.inject.Inject;
import java.util.Date;
import java.util.List;

@Component
@Scope("request")
public class MemberTimeSlotScheduleController {

    private final MemberTimeSlotScheduleService memberTimeSlotScheduleService;

    private final MemberTimeSlotScheduleModel memberTimeSlotScheduleModel;

    @Inject
    public MemberTimeSlotScheduleController(MemberTimeSlotScheduleService memberTimeSlotScheduleService, MemberTimeSlotScheduleModel memberTimeSlotScheduleModel) {
        this.memberTimeSlotScheduleService = memberTimeSlotScheduleService;
        this.memberTimeSlotScheduleModel = memberTimeSlotScheduleModel;
    }

    public void init() {
        if (FacesContext.getCurrentInstance().isPostback() == false) {
            memberTimeSlotScheduleModel.reset();
            initSchedule();
        }
    }

    public void onEventSelect(ScheduleEntrySelectEvent selectEvent) {
        LoodelScheduleEvent selectedScheduleEvent = (LoodelScheduleEvent) selectEvent.getScheduleEvent();
        final String selectedLearningEventId = ((TimeSlotScheduleData) selectedScheduleEvent.getData()).getLearningEventId();
        this.memberTimeSlotScheduleModel.setLearningEventVoteData(memberTimeSlotScheduleService.getLearningEventVoteData(selectedLearningEventId));
        final ScheduleModel scheduleModel = memberTimeSlotScheduleModel.getScheduleModel();
        initSelectedLearningEvents(selectedLearningEventId, scheduleModel);
    }

    private void initSelectedLearningEvents(String selectedLearningEventId, ScheduleModel scheduleModel) {
        Assert.notNull(scheduleModel);
        if (StringUtils.isNotEmpty(selectedLearningEventId)) {
            for (ScheduleEvent event : scheduleModel.getEvents()) {
                LoodelScheduleEvent otherLoodelScheduleEvent = (LoodelScheduleEvent) event;
                final TimeSlotScheduleData otherTimeSlotScheduleData = (TimeSlotScheduleData) otherLoodelScheduleEvent.getData();
                otherLoodelScheduleEvent.setSelectedEvent(otherTimeSlotScheduleData.getLearningEventId().equals(selectedLearningEventId));
                scheduleModel.updateEvent(otherLoodelScheduleEvent);
            }
        }
    }

    private void initSchedule() {
        ScheduleModel scheduleModel = new LazyScheduleModel() {
            @Override
            public void loadEvents(Date start, Date end) {
                final List<TimeSlotScheduleData> timeSlotScheduleDataList = memberTimeSlotScheduleService.searchTimeSlotsByCriteria(adjustTimeSlotScheduleSearchCriteria(start, end));
                for (TimeSlotScheduleData timeSlotScheduleData : timeSlotScheduleDataList) {
                    this.addEvent(LoodelScheduleEventFactory.createNewScheduleEvent(timeSlotScheduleData));
                }
                // Needs to be set here since primeFaces invokes this loadEvents(...) method every request (also after an event has been selected)
                final LearningEventVoteData learningEventVoteData = memberTimeSlotScheduleModel.getLearningEventVoteData();
                if (learningEventVoteData != null) {
                    initSelectedLearningEvents(learningEventVoteData.getLearningEventId(), this);
                }
            }
        };
        memberTimeSlotScheduleModel.setScheduleModel(scheduleModel);
    }

    private TimeSlotScheduleSearchCriteria adjustTimeSlotScheduleSearchCriteria(Date start, Date end) {
        final TimeSlotScheduleSearchCriteria timeSlotScheduleSearchCriteria = memberTimeSlotScheduleModel.getTimeSlotScheduleSearchCriteria();
        timeSlotScheduleSearchCriteria.setStartDateRange(new LocalDate(start));
        timeSlotScheduleSearchCriteria.setEndDateRange(new LocalDate(end));
        return timeSlotScheduleSearchCriteria;
    }

}
